Public Class MessageWindow
	Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

	Public Sub New()
		MyBase.New()

		'This call is required by the Windows Form Designer.
		InitializeComponent()

		'Add any initialization after the InitializeComponent() call
	End Sub

	'Form overrides dispose to clean up the component list.
	Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
		If disposing Then
			If Not (components Is Nothing) Then
				components.Dispose()
			End If
		End If
		MyBase.Dispose(disposing)
	End Sub

	'Required by the Windows Form Designer
	Private components As System.ComponentModel.IContainer

	'NOTE: The following procedure is required by the Windows Form Designer
	'It can be modified using the Windows Form Designer.  
	'Do not modify it using the code editor.
	Friend WithEvents btnSend As System.Windows.Forms.Button
	Friend WithEvents rtbChat As System.Windows.Forms.RichTextBox
	Friend WithEvents txtMessage As System.Windows.Forms.TextBox
	Friend WithEvents mnuRichText As System.Windows.Forms.ContextMenu
	Friend WithEvents mnuCopy As System.Windows.Forms.MenuItem
	Friend WithEvents mnuClear As System.Windows.Forms.MenuItem
	Friend WithEvents mnuSep1 As System.Windows.Forms.MenuItem
	<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
		Dim resources As System.Resources.ResourceManager = New System.Resources.ResourceManager(GetType(MessageWindow))
		Me.btnSend = New System.Windows.Forms.Button()
		Me.rtbChat = New System.Windows.Forms.RichTextBox()
		Me.mnuRichText = New System.Windows.Forms.ContextMenu()
		Me.mnuCopy = New System.Windows.Forms.MenuItem()
		Me.mnuSep1 = New System.Windows.Forms.MenuItem()
		Me.mnuClear = New System.Windows.Forms.MenuItem()
		Me.txtMessage = New System.Windows.Forms.TextBox()
		Me.SuspendLayout()
		'
		'btnSend
		'
		Me.btnSend.Anchor = (System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right)
		Me.btnSend.Enabled = False
		Me.btnSend.Location = New System.Drawing.Point(360, 248)
		Me.btnSend.Name = "btnSend"
		Me.btnSend.Size = New System.Drawing.Size(96, 48)
		Me.btnSend.TabIndex = 1
		Me.btnSend.Text = "Send"
		'
		'rtbChat
		'
		Me.rtbChat.Anchor = (((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
		   Or System.Windows.Forms.AnchorStyles.Left) _
		   Or System.Windows.Forms.AnchorStyles.Right)
		Me.rtbChat.ContextMenu = Me.mnuRichText
		Me.rtbChat.Font = New System.Drawing.Font("Tahoma", 10.8!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(204, Byte))
		Me.rtbChat.Location = New System.Drawing.Point(8, 8)
		Me.rtbChat.Name = "rtbChat"
		Me.rtbChat.ReadOnly = True
		Me.rtbChat.Size = New System.Drawing.Size(448, 232)
		Me.rtbChat.TabIndex = 5
		Me.rtbChat.TabStop = False
		Me.rtbChat.Text = ""
		'
		'mnuRichText
		'
		Me.mnuRichText.MenuItems.AddRange(New System.Windows.Forms.MenuItem() {Me.mnuCopy, Me.mnuSep1, Me.mnuClear})
		'
		'mnuCopy
		'
		Me.mnuCopy.Index = 0
		Me.mnuCopy.Text = "Copy"
		'
		'mnuSep1
		'
		Me.mnuSep1.Index = 1
		Me.mnuSep1.Text = "-"
		'
		'mnuClear
		'
		Me.mnuClear.Index = 2
		Me.mnuClear.Text = "Clear"
		'
		'txtMessage
		'
		Me.txtMessage.Anchor = ((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left) _
		   Or System.Windows.Forms.AnchorStyles.Right)
		Me.txtMessage.Location = New System.Drawing.Point(8, 248)
		Me.txtMessage.Multiline = True
		Me.txtMessage.Name = "txtMessage"
		Me.txtMessage.Size = New System.Drawing.Size(344, 48)
		Me.txtMessage.TabIndex = 0
		Me.txtMessage.Text = ""
		'
		'MessageWindow
		'
		Me.AcceptButton = Me.btnSend
		Me.AutoScaleBaseSize = New System.Drawing.Size(6, 15)
		Me.ClientSize = New System.Drawing.Size(464, 304)
		Me.Controls.AddRange(New System.Windows.Forms.Control() {Me.txtMessage, Me.rtbChat, Me.btnSend})
		Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon)
		Me.KeyPreview = True
		Me.MinimumSize = New System.Drawing.Size(300, 200)
		Me.Name = "MessageWindow"
		Me.ShowInTaskbar = False
		Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show
		Me.Text = "Chat"
		Me.ResumeLayout(False)

	End Sub

#End Region

	Public Event ShouldBroadcastText(ByVal Text As String)

	'====================================================================

#Region " Log messages in RichTextBox"

	Public Sub Log(ByVal Text As String, ByVal TextColor As System.Drawing.Color)
		' The length of existing text.
		Dim EndPosition As Integer = rtbChat.TextLength

		' The new text being added.
		Dim sb As New System.Text.StringBuilder(Text.Length + 10)
		sb.Append("[")
		sb.Append(DateTime.Now.ToShortTimeString)
		sb.Append("] ")
		sb.Append(Text)
		sb.Append(Environment.NewLine)		  ' OS-independent NewLine character(s)
		Dim NewText As String = sb.ToString

		' prevent RichTextBox from flickering...
		If Me.Visible Then LockWindowUpdate(rtbChat.Handle.ToInt32)

		' Append new message to the bottom
		rtbChat.AppendText(NewText)
		rtbChat.SelectionStart = EndPosition
		rtbChat.SelectionLength = NewText.Length
		rtbChat.SelectionColor = TextColor
		rtbChat.SelectionStart = rtbChat.TextLength - 1

		' Use the special trick to scroll the RichTextBox to the end.
		' Default Microsoft implementation doesn't allow to do it
		' in a simple way, without focusing the text box.
		ScrollTextBoxToEnd(rtbChat.Handle, rtbChat.Height)

		' don't forget to enable back the RichTextBox update
		If Me.Visible Then LockWindowUpdate(IntPtr.Zero.ToInt32)
	End Sub

	' no parameters version
	Public Sub Log(ByVal Text As String)
		Log(Text, Drawing.SystemColors.WindowText)
	End Sub

#End Region

#Region " RichTextBox context menu events "

	Private Sub mnuCopy_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles mnuCopy.Click
		rtbChat.Copy()
	End Sub

	Private Sub mnuClear_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles mnuClear.Click
		rtbChat.Clear()
	End Sub

#End Region

#Region " Send button "

	'====================================================================
	' Enable Send button
	'====================================================================

	Private Sub txtMessage_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtMessage.TextChanged
		EnableSend()
	End Sub

	Private Sub txtMessage_Enter(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtMessage.Enter
		EnableSend()
	End Sub

	Private Sub EnableSend()
		btnSend.Enabled = txtMessage.TextLength > 0
	End Sub

	'====================================================================
	' Send
	'====================================================================

	Private Sub btnSend_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSend.Click
		If Me.Visible AndAlso btnSend.Enabled Then
			Send()
		End If
	End Sub

	Private Sub Send()
		Log(txtMessage.Text, colMe)
		RaiseEvent ShouldBroadcastText(txtMessage.Text)
		txtMessage.Clear()
		txtMessage.Focus()
	End Sub

	'====================================================================

#End Region

	'====================================================================

#Region " Window behaviour "

	'====================================================================
	' Show the form explicitly to create its native window and to start its message loop
	' Prepare ChatWindow to be showable.
	' This creates the native window physically and implicitly launches its message loop.
	'====================================================================
	Public Sub InitializeWindow()
		Me.Opacity = 0
		Me.Show()
		Me.Hide()
		Me.Opacity = 1
	End Sub

#Region " Closing the form "

	' Reason for closing the form 
	Private ClosedFromUI As Boolean = False

	'====================================================================
	' Form Close behavior. Because this form isn't the main form, its closing
	' should be equivalent to its minimizing.
	'====================================================================
	Private Sub MessageWindow_Closing(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
		If ClosedFromUI Then
			e.Cancel = True
			MinimizedToTray = True
			ClosedFromUI = False
		End If
	End Sub

	'====================================================================
	' Subclassing to spy on some useful window messages
	'====================================================================

	Private Const SC_CLOSE As Int32 = &HF060
	Private Const SC_MINIMIZE As Long = &HF020&
	Private Const WM_SYSCOMMAND As Int32 = &H112

	Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
		If m.Msg = WM_SYSCOMMAND Then
			If m.WParam.ToInt32() = SC_CLOSE Then			 ' Close button of the form pushed.
				ClosedFromUI = True
			ElseIf m.WParam.ToInt32 = SC_MINIMIZE Then			 ' Minimize button pushed.
				MinimizedToTray = True
				Return
			End If
		End If
		MyBase.WndProc(m)
	End Sub

	'====================================================================

#End Region

#Region " Minimize and Restore "

	'====================================================================
	' Minimize and Restore
	'====================================================================

	Private Sub MessageWindow_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
		Select Case e.KeyCode
			Case Keys.Escape
				MinimizeToTray()
		End Select
	End Sub

	'====================================================================

	Public Property MinimizedToTray() As Boolean
		Get
			Return Not Me.Visible
		End Get
		Set(ByVal Value As Boolean)
			If Value Then MinimizeToTray() Else Restore()
		End Set
	End Property

	'====================================================================

	Private Sub MinimizeToTray()
		If Me.Visible Then Me.Hide()
	End Sub

	Private Sub Restore()
		If Not Me.Visible Then
			Me.Show()
			Me.Activate()			 ' do I need this?
		End If
		If Me.WindowState = FormWindowState.Minimized Then Me.WindowState = FormWindowState.Normal
		Me.txtMessage.Focus()
	End Sub

	'====================================================================

#End Region

	'====================================================================

#End Region

	'====================================================================

End Class